// GCStock.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <afxinet.h>
#include "psapi.h"
#include "main.h"

#include "GCHeader.h"
#include "GCRawDataInterface.h"
#include "GCData.h"
#include "GCString.h"
#include "GCArray.h"
#include "GCTime.h"
#include "GCStock.h"
using namespace std;
using namespace gcstock;

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

void removeTags(CString& data,CStringArray& array,CString &timeStamp);
CString removeTag(CString& data, CString tag = _T(""));
int findLMatch(CString& data, int idx);
int findRMatch(CString& data, int idx);
CString getTag(CString& data,int begin,int end, GCBOOL bEnd = FALSE);
int parseMsg(CHttpFile* HTTPFile, CString &tempStamp,CString& latestRetrTime);
    

/////////////////////////////////////////////
// _tmain
// purpose	:
// input	:
// output	:
// return	:
//
/////////////////////////////////////////////
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;
    
    // initialize MFC and print and error on failure
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
        // TODO: change error code to suit your needs
        cerr << _T("Fatal Error: MFC initialization failed") << endl;
        nRetCode = 1;
    }
    else
    {
        // TODO: code your application's behavior here.
        CString strHello;
        strHello.LoadString(IDS_HELLO);
        cout << (LPCTSTR)strHello << endl;
        
//         HMODULE kernel32 = LoadLibraryA("kernel32.dll");   
//         VOID (*GlobalMemoryStatus)(LPMEMORYSTATUS lpBuffer);
//         GlobalMemoryStatus = GetProcAddress(kernel32,"GlobalMemoryStatus");
        CInternetSession*   Session   =   new   CInternetSession(); 
        CHttpFile*   HTTPFile; 
        
        
       

        CString curTimeStamp;
        CString latestRetrTime = _T("");

        GCStockMonitorQQ qqStock;
        qqStock.setParseFormat();
        
        /* Data source: */
        /* http://hq.sinajs.cn/rn=1278380347183&list=sz002202       -- sina */
        /* http://api.money.163.com/data/feed/0601299               -- 163 */
        /* http://quotes.money.163.com/_trade/0601299.html          -- 163 */
        /* http://qt.gtimg.cn/r=0.1470958897843957q=sh601299        -- dynamic data qq  */
        /* http://stock.gtimg.cn/data/index.php?appn=detail&action=data&c=sh601299&p=0  -- static data qq */
        /* http://flashquote.stock.hexun.com/Stock_Combo.ASPX?mc=1_601299&dt=MX,DL&t=0.34493990521878004 -- hexun */
        /* I will find out URL of Yahoo tomorrow */
        //HTTPFile   =   (CHttpFile*)Session->OpenURL("http://vip.stock.finance.sina.com.cn/quotes_service/view/vMS_tradedetail.php?symbol=sz002202"); 
        CHttpConnection* pConnection;
        while(TRUE)
        {
            GCBOOL result;
            try
            {
                pConnection = Session->GetHttpConnection(_GCT("qt.gtimg.cn"));
                HTTPFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_GET,
                    _GCT("r=0.1470958897843957q=sh601299,sh600016"),
                    NULL,
                    1,
                    NULL,
                    NULL,
                    INTERNET_FLAG_DONT_CACHE);
                //         HTTPFile   =   (CHttpFile*)Session->OpenURL(
                //             "http://qt.gtimg.cn/r=0.1470958897843957q=sh601299,sh600016"); 
                ASSERT(HTTPFile);
                
                
                result = HTTPFile->SendRequest();
            }
            catch(exception e)
            {
                pConnection->Close();
            }
            if (result==TRUE)
            {
                CString line;
                while(HTTPFile->ReadString(line))
                {
                    qqStock.parseLine(line.GetBuffer(line.GetLength() + 1));
                    try
                    {
                        //gccout<<qqStock.toString()<<gcendl;
                    }
                    catch(exception e)
                    {
                        gccout<<e.what()<<gcendl;
                    }
                    line.ReleaseBuffer();
                }
                //parseStaticWeb(HTTPFile,tempStamp,latestRetrTime, curTimeStamp);
                //parseMsg(HTTPFile, tempStamp, latestRetrTime);
                line.Empty();
                HTTPFile->Close();
                delete HTTPFile;  
                HTTPFile = NULL;
                pConnection->Close();
                delete pConnection;
                pConnection = NULL;
            }
          
            Sleep(100);            
        }
        system("pause");
       
    }
    return nRetCode;
}    

/////////////////////////////////////////////
// parseMsg
// purpose	:
// input	:
// output	:
// return	:
//
/////////////////////////////////////////////
int parseMsg(CHttpFile* HTTPFile, CString &tempStamp,CString& latestRetrTime)
{
    CString line;
    
    while(HTTPFile->ReadString(line))
    {
        //cout<<(LPCTSTR)line<<endl;

    }
   // system("pause");
    return 1;
}// 

/////////////////////////////////////////////
// parseStaticWeb
// purpose	:
// input	:
// output	:
// return	:
//
/////////////////////////////////////////////
int parseStaticWeb(CHttpFile *HTTPFile, CString& tempStamp, CString& latestRetrTime,CString& curTimeStamp)
{
    CString line;
    // Boolean to identify whether the table datatbl has been reached for current session
    GCBOOL bIsTable = FALSE;


    while(HTTPFile->ReadString(line))
    {   
        
        if(-1 != line.Find(_T("<table class=\"datatbl\" id=\"datatbl\">")))
        {
            bIsTable = TRUE;
        }
        if(bIsTable)
        {
            int begin = line.Find(_T("<tr"));
            int end = line.Find(_T("</tr>"));
            //             TRACE("begin is %d\n",begin);
            //             TRACE("end is %d\n",end);
            
            if(begin != -1 &&
                end > 0)
            {
                // remove <tr...>...</tr>
                begin = line.Find(_T(">"));
                // Store current line without the beginning tag and end tag
                CString chgLine = line.Mid(begin + 1, end - begin - 1);
                //Store this line in an array
                CStringArray array;
                removeTags(chgLine,array,curTimeStamp);
                cout<<endl;
                //If it is the first record of current retrieve, save the timestamp
                if(tempStamp == "" )
                {
                    tempStamp = curTimeStamp; 
                }
                //If the timestamp of current retrieve is before the latestRetrTime, stop to retrieve
                if(curTimeStamp <= latestRetrTime )
                {
                    cout<< "Old data passed" <<endl;
                    break;
                }
                // update array to database
            }    
        }
        
    }
    //Update latestRetrTime
    latestRetrTime = tempStamp;
    HTTPFile->Close();
    delete HTTPFile;
    HTTPFile = NULL;
    //Session->Close();
    return 1;
}


/////////////////////////////////////////////
// removeTags
// purpose	:   get value in html context one by one
// input	:   data:   html context
//              
// output	:   data: context removed tag
//              array:  store values
// return	:   void
//
/////////////////////////////////////////////
void removeTags(CString& data,CStringArray& array,CString &timeStamp)
{
    GCBOOL bRecord = FALSE;
    while(data.GetLength()>0)
    {
        
        CString value = removeTag(data/*, data.Mid(lMatch + 1,rMatch - 1)*/);
        
        cout<<LPCTSTR(value)<<"\t";
        if(FALSE == bRecord)
        {
            timeStamp = value;
            bRecord = TRUE;
        }
        array.Add(value); 
        
    }
}

/////////////////////////////////////////////
// removeTag
// purpose	:
// input	:
// output	:
// return	:
//
/////////////////////////////////////////////
CString removeTag(CString& data,CString tag)
{
    int begin = data.Find(_T("<"));
    int end = data.Find(_T("</"),begin);
    int rMatch1, rMatch2;
    CString value = "";
    CString beginTag = _T("");
    CString endTag = _T("");

    if (begin != -1 && end != -1)
    {
        rMatch1 = findRMatch(data,begin);
        beginTag = getTag(data,begin,rMatch1);
        while(TRUE)
        {
            rMatch2 = findRMatch(data,end);
            endTag = getTag(data,end,rMatch2,TRUE);

            if(beginTag == endTag)
            {
                value = removeTag(data.Mid(rMatch1 + 1, end - rMatch1 - 1));
                break;
            }
            else
            {
                end = data.Find(_T("</"),end + 1);
            }
            
        }
    }
    else
    {
        value = data;
    }
    data = data.Mid(rMatch2 + 1);
    return value;
}

/////////////////////////////////////////////
// findRMatch
// purpose	:
// input	:
// output	:
// return	:
//
/////////////////////////////////////////////
int findRMatch(CString& data, int idx)
{
    return data.Find(_T(">"),idx);
}

/////////////////////////////////////////////
// findLMatch
// purpose	:
// input	:
// output	:
// return	:
//
/////////////////////////////////////////////
int findLMatch(CString& data, int idx)
{
    return data.Find(_T("<"),idx);
}

/////////////////////////////////////////////
// getTag
// purpose	:
// input	:
// output	:
// return	:
//
/////////////////////////////////////////////
CString getTag(CString& data,int begin,int end, GCBOOL bEnd)
{
    int blank = data.Find(_T(" "),begin);
    int first = bEnd?begin + 2:begin + 1;
    if (blank >= 0 && blank < end)
    {
        return data.Mid(first, blank - first);
    }
    return data.Mid(first, end - first);
}